﻿namespace Bowlus.FrontEnd.PortalAdminService
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Linq;
    using System.Web.Script.Serialization;
    using Bowlus.Common;
    using Bowlus.Common.Communications;
    using Microsoft.WindowsAzure.ServiceRuntime;

    public class AdminService : IAdminService
    {
        private readonly Dictionary<Guid, BowlusMessage> messageTracker;

        private readonly CommunicationsClient deploymentServiceClient;

        public AdminService()
        {
            this.deploymentServiceClient = new CommunicationsClient();
            this.messageTracker = new Dictionary<Guid, BowlusMessage>();
        }

        public Dictionary<Guid, BowlusMessage> MessageTracker
        {
            get
            {
                return this.messageTracker;
            }
        }

        public string GetTenantDeployment()
        {
            var tenantDep = TenantDeploymentsStore.Instance.TenantDeployment.ToList();

            var serializer = new JavaScriptSerializer();

            return serializer.Serialize(tenantDep);
        }

        /*
         * return application list: site1.1.zip, site1.2.zip, ect...
         */
        public string GetApplications()
        {
            IAppRepository appRepository = new StorageAppRepository("System.ConnectionString");
            Collection<string> appList = appRepository.GetAppList();

            var serializer = new JavaScriptSerializer();
            return serializer.Serialize(appList);
        }

        /*
         * return customization list: site1.1.1.zip, site1.1.2.zip, ect...
         */
        public string GetCustomizations(string application)
        {
            string appName = Path.GetFileNameWithoutExtension(application);
            IAppRepository appRepository = new StorageAppRepository("System.ConnectionString");
            Collection<string> custList = appRepository.GetCustomizationList(appName);

            var serializer = new JavaScriptSerializer();
            return serializer.Serialize(custList);
        }

        /// <summary>
        /// Create new tenant in Tenant deployment table. This tenant will later be allocated a instance, and then be deployed.
        /// </summary>
        /// <param name="tenantId">
        /// The tenant id.
        /// </param>
        /// <param name="application">
        /// The application.
        /// </param>
        /// <param name="customization"> </param>
        /// <returns>
        /// A status string
        /// </returns>
        public string CreateTenant(string tenantId, string application, string customization)
        {
            var tenantDeployment = new TenantDeployment
                {
                    Application = application,
                    Customizations = customization,
                    TenantId = tenantId,
                    HostName = Settings.TenantHostFromConfigFormat(tenantId)
                };

            var message = new BowlusMessage
                {
                    MessageType = BowlusMessageType.DeployApp,
                    Body = tenantDeployment.Serialize(),
                    Sender = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[Settings.FrontEndRoleName].IPEndpoint,
                };

            this.deploymentServiceClient.SendMessageToRoleInstance(
                message, RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[Settings.FrontEndRoleName].IPEndpoint, Settings.FrontEndRoleName);

            return "Request submitted.";
        }

        /*
         * Get instance health status.
         */
        public string GetInstanceStatus()
        {
            var healthStatus = new HealthStatus
                {
                    ArrInstances = new List<InstanceState>(),
                    AppHostInstances = new List<InstanceState>()
                };

            // TODO: Update this to use the service management API w/caching
            // RoleEnvironment information does not provide Status on an instance
            var roleInstances = RoleEnvironment.Roles[Settings.FrontEndRoleName];
            foreach (var instance in roleInstances.Instances)
            {
                healthStatus.ArrInstances.Add(new InstanceState { Title = instance.Id, Status = "Ready" });
            }

            roleInstances = RoleEnvironment.Roles[Settings.AppHostRoleName];
            foreach (var instance in roleInstances.Instances)
            {
                try
                {
                    var instanceState = new InstanceState { Title = instance.Id, Status = "Ready" };
                    healthStatus.AppHostInstances.Add(instanceState);

                    // this linq statement seems to be throwing a bad input exception
                    RoleInstance instance1 = instance;
                    var tenantDeployments = from tenantDeployment in TenantDeploymentsStore.Instance.TenantDeployment
                                            where tenantDeployment.AppHostInstanceId.Equals(instance1.Id)
                                            select new InstanceStateItem { Text = tenantDeployment.TenantId, Status = tenantDeployment.Status };

                    instanceState.Items.AddRange(tenantDeployments.ToArray().OrderBy(t => t.Text));
                }
                catch (System.Data.Services.Client.DataServiceQueryException ex)
                {
                    System.Diagnostics.Trace.Write(ex.ToString());
                }
            }

            var serializer = new JavaScriptSerializer();

            return serializer.Serialize(healthStatus);
        }

        public string IsInfrastructureReady()
        {
            var serializer = new JavaScriptSerializer();

            var result = HostingInfrastructureStore.InfrastructureReady;
            return serializer.Serialize(result);
        }
    }
}
